package com.xyht.sca_s.student_manage_system.modules.agreement.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.data.PictureRenderData;
import com.deepoove.poi.data.PictureType;
import com.deepoove.poi.data.Pictures;
import com.deepoove.poi.data.TextRenderData;
import com.deepoove.poi.data.style.Style;
import com.deepoove.poi.policy.PictureRenderPolicy;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.spire.doc.Document;
import com.spire.doc.FileFormat;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonCodeEnum;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonResult;
import com.xyht.sca_s.student_manage_system.common.commonReturn.ExceptionCast;
import com.xyht.sca_s.student_manage_system.common.commonReturn.ResponseResult;
import com.xyht.sca_s.student_manage_system.common.util.*;
import com.xyht.sca_s.student_manage_system.modules.agreement.entity.SmsAgreementApplication;
import com.xyht.sca_s.student_manage_system.modules.agreement.entity.SmsAgreementApplicationDetail;
import com.xyht.sca_s.student_manage_system.modules.agreement.entity.SmsAgreementApplicationProcess;
import com.xyht.sca_s.student_manage_system.modules.agreement.entity.dto.*;
import com.xyht.sca_s.student_manage_system.modules.agreement.entity.vo.*;
import com.xyht.sca_s.student_manage_system.modules.agreement.mapper.SmsAgreementApplicationDetailMapper;
import com.xyht.sca_s.student_manage_system.modules.agreement.mapper.SmsAgreementApplicationMapper;
import com.xyht.sca_s.student_manage_system.modules.agreement.mapper.SmsAgreementApplicationMpjMapper;
import com.xyht.sca_s.student_manage_system.modules.agreement.mapper.SmsAgreementApplicationProcessMapper;
import com.xyht.sca_s.student_manage_system.modules.agreement.service.SmsAgreementApplicationService;
import com.xyht.sca_s.student_manage_system.modules.common.constant.FileSavePathConstant;
import com.xyht.sca_s.student_manage_system.modules.newTips.entity.SmsNewTips;
import com.xyht.sca_s.student_manage_system.modules.newTips.entity.SmsNewTipsRecord;
import com.xyht.sca_s.student_manage_system.modules.newTips.mapper.SmsNewTipsMapper;
import com.xyht.sca_s.student_manage_system.modules.newTips.mapper.SmsNewTipsRecordMapper;
import com.xyht.sca_s.student_manage_system.modules.newTips.myEnum.AppTypeEnum;
import com.xyht.sca_s.student_manage_system.modules.newTips.myEnum.RangeTypeEnum;
import com.xyht.sca_s.student_manage_system.modules.newTips.myEnum.TipsTypeEnum;
import com.xyht.sca_s.student_manage_system.modules.newTips.util.NewTipsUtil;
import com.xyht.sca_s.student_manage_system.modules.org.mapper.SmsOrgStructureMapper;
import com.xyht.sca_s.student_manage_system.modules.org.mapper.SmsOrgUserRelationMapper;
import com.xyht.sca_s.student_manage_system.modules.student.constant.StudentInfoCommonConstant;
import com.xyht.sca_s.student_manage_system.modules.user.entity.SmsRole;
import com.xyht.sca_s.student_manage_system.modules.user.entity.SmsUser;
import com.xyht.sca_s.student_manage_system.modules.user.mapper.SmsRoleMapper;
import com.xyht.sca_s.student_manage_system.modules.user.mapper.SmsUserMapper;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDType0Font;
import org.apache.pdfbox.pdmodel.graphics.state.PDExtendedGraphicsState;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.springframework.beans.BeanUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

import static com.xyht.sca_s.student_manage_system.common.util.ParamCheckUtil.isNullOrEmpty;
import static com.xyht.sca_s.student_manage_system.modules.agreement.constant.agreementApplicationStatusConstant.*;
import static com.xyht.sca_s.student_manage_system.modules.agreement.constant.agreementApplicationTypeConstant.*;
import static com.xyht.sca_s.student_manage_system.modules.agreement.constant.agreementObjectTypeConstant.AGREEMENT_OBJECT_TYPE_PERSON;
import static com.xyht.sca_s.student_manage_system.modules.agreement.constant.agreementObjectTypeConstant.AGREEMENT_OBJECT_TYPE_ROLE;
import static com.xyht.sca_s.student_manage_system.modules.examinePaymentEquipment.constant.isExportProcessConstant.EXPORT_PROCESS_TRUE;
import static com.xyht.sca_s.student_manage_system.modules.examinePaymentEquipment.constant.paymentExamineStatusConstant.*;
import static com.xyht.sca_s.student_manage_system.modules.newTips.myEnum.CopyTypeEnum.COPY_TYPE_ENUM_NONE;
import static com.xyht.sca_s.student_manage_system.modules.visitor.contact.CheckType.PROCESS_PEOPLE_CHECK_TYPE;
import static com.xyht.sca_s.student_manage_system.modules.workApplication.constant.workApplicationStatusConstant.*;
import static com.xyht.sca_s.student_manage_system.modules.workApplicationGroup.constant.SortTypeConstant.SORT_TYPE_ALLOW_STATUS;
import static com.xyht.sca_s.student_manage_system.modules.workApplicationGroup.constant.SortTypeConstant.SORT_TYPE_TIME;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author XYHT
 * @since 2023-06-11
 */
@Service
public class SmsAgreementApplicationServiceImpl extends ServiceImpl<SmsAgreementApplicationMapper, SmsAgreementApplication> implements SmsAgreementApplicationService {

    @Resource
    private FileSavePathConstant fileSavePathConstant;
    @Resource
    SmsAgreementApplicationMapper smsAgreementApplicationMapper;
    @Resource
    SmsAgreementApplicationProcessMapper smsAgreementApplicationProcessMapper;
    @Resource
    SmsAgreementApplicationDetailMapper smsAgreementApplicationDetailMapper;
    @Resource
    NewTipsUtil newTipsUtil;
    @Resource
    CacheUtil cacheUtil;
    @Resource
    SmsAgreementApplicationMpjMapper smsAgreementApplicationMpjMapper;
    @Resource
    PinYinUtil pinYinUtil;
    @Resource
    SmsOrgStructureMapper smsOrgStructureMapper;
    @Resource
    XWPFTUtil xwpftUtil;
    @Resource
    SmsOrgUserRelationMapper smsOrgUserRelationMapper;
    @Resource
    SmsUserMapper smsUserMapper;
    @Resource
    ApiModelUtil apiModelUtil;
    @Resource
    SmsRoleMapper smsRoleMapper;
    @Resource
    private SmsNewTipsMapper smsNewTipsMapper;
    @Resource
    private SmsNewTipsRecordMapper smsNewTipsRecordMapper;

    @Transactional
    @Override
    public ResponseResult addAgreement(SmsAgreementApplicationVO applicationVO, String user_id) {
        List<SmsAgreementApplicationProcess> fillProcessList =
                smsAgreementApplicationProcessMapper.selectList(new QueryWrapper<SmsAgreementApplicationProcess>()
                        .lambda()
                        .eq(SmsAgreementApplicationProcess::getProcessIsApplicationEdit, true)
                        .eq(SmsAgreementApplicationProcess::getProcessIsUse, true)
                        .orderByAsc(SmsAgreementApplicationProcess::getProcessSort));
        if (fillProcessList != null && fillProcessList.size() > 0) {
            if (applicationVO.getProcessList() == null || applicationVO.getProcessList().size() < 1) {
                return CommonResult.failed(CommonCodeEnum.AGREEMENT_ALLOW_USER_NOT_SETTING);
            }
            //判断申请人是否将全部需要编辑流程填写
            List<SmsAgreementApplicationProcess> filterList = fillProcessList
                    .stream()
                    .filter(process -> {
                                List<String> result = applicationVO.getProcessList()
                                        .stream()
                                        .filter(fillProcess -> fillProcess.getProcessId().equals(process.getId()))
                                        .map(SmsAgreementApplicationDetailVO::getId)
                                        .collect(Collectors.toList());
                                //匹配的去除  未匹配的留下
                                if (result.size() > 0) {
                                    return false;
                                } else {
                                    return true;
                                }
                            }
                    )
                    .collect(Collectors.toList());
            if (filterList.size() > 0) {
                return CommonResult.failed(CommonCodeEnum.AGREEMENT_ALLOW_PROCESS_NOT_FILL);
            }
        }
        //统计申请表数量
//        Integer contractCount = smsAgreementApplicationMapper.selectCount(new QueryWrapper<>());
        //创建申请表
        SmsAgreementApplication addApplication = new SmsAgreementApplication();
        BeanUtils.copyProperties(applicationVO, addApplication);
        addApplication.setApplicationApplyUserId(user_id);
        addApplication.setAllowStatus(AGREEMENT_STATUS_WAIT_ALLOW);
        smsAgreementApplicationMapper.insert(addApplication);

//        QueryWrapper<SmsOrgStructure> queryWrapper = new QueryWrapper<>();
//        queryWrapper.lambda().eq(SmsOrgStructure::getId, applicationVO.getOrganizationId());
//        SmsOrgStructure smsOrgStructure = smsOrgStructureMapper.selectOne(queryWrapper);
//        if (isNullOrEmpty(smsOrgStructure)) {
//            return CommonResult.failed(CommonCodeEnum.AGREEMENT_ORG_NOT_FIND);
//        }
//        String name = smsOrgStructure.getOrgName();
//        String newName = pinYinUtil.getHanZiPY(name);

//        String contractNo = newName + new SimpleDateFormat("yyyy")
//                .format(new Date()) + String.format("%04d", contractCount + 1);
//        SmsAgreementApplication application = new SmsAgreementApplication();
//        BeanUtils.copyProperties(addApplication, application);
//        application.setProjectContractNum(contractNo);
//        smsAgreementApplicationMapper.updateById(application);

        if (addApplication.getId() == null) {
            ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.FAIL));
        }
        String application_id = addApplication.getId();

        //创建审批流程
        List<SmsAgreementApplicationProcess> originProcessList =
                smsAgreementApplicationProcessMapper.selectList(new QueryWrapper<SmsAgreementApplicationProcess>()
                        .lambda()
                        .eq(SmsAgreementApplicationProcess::getProcessIsUse, true)
                        .orderByAsc(SmsAgreementApplicationProcess::getProcessSort));
        if (originProcessList == null || originProcessList.size() < 1) {
            ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.AGREEMENT_PROCESS_NOT_SETTING));
        }
        int sort = 1;
        for (SmsAgreementApplicationProcess process : originProcessList) {
            //判断管理员是否配置初始流程
            if (!process.getProcessIsApplicationEdit()) {
                if (isNullOrEmpty(process.getProcessObjectId()) || isNullOrEmpty(process.getProcessObjectType())) {
                    ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.AGREEMENT_PROCESS_NOT_SETTING));
                }
            }
            if(!applicationVO.getIsOpenHouQin()){
                if(process.getProcessName().equals("后勤部")){
                    continue;
                }
            }


            SmsAgreementApplicationDetail addDetail =
                    new SmsAgreementApplicationDetail();

            addDetail.setApplicationId(application_id);
            addDetail.setProcessId(process.getId());
            addDetail.setProcessIsSign(process.getProcessIsSign());
            addDetail.setProcessIsStamp(process.getProcessIsStamp());
            addDetail.setProcessName(process.getProcessName());
            addDetail.setDetailAllowStatus(AGREEMENT_STATUS_WAIT_ALLOW);

            addDetail.setDetailSort(sort++);

            //申请人可编辑流程
            if (process.getProcessIsApplicationEdit()) {
                List<SmsAgreementApplicationDetailVO> filterList = applicationVO.getProcessList()
                        .stream()
                        .filter(fillProcess -> fillProcess.getProcessId().equals(process.getId()))
                        .collect(Collectors.toList());
                if (filterList.size() < 1) {
                    ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.AGREEMENT_ALLOW_PROCESS_NOT_FILL));
                }
                SmsAgreementApplicationDetailVO fillProcessReq = filterList.get(0);

                if (isNullOrEmpty(fillProcessReq.getProcessObjectId())) {
                    ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.INVALID_PARAM));
                }
                addDetail.setProcessObjectId(fillProcessReq.getProcessObjectId());
                addDetail.setProcessObjectType(AGREEMENT_OBJECT_TYPE_PERSON);
            } else {
                addDetail.setProcessObjectId(process.getProcessObjectId());
                addDetail.setProcessObjectType(process.getProcessObjectType());
            }
            smsAgreementApplicationDetailMapper.insert(addDetail);
        }

        //消息通知
        //通知流程第一个节点
        SmsAgreementApplicationDetail firstDetail =
                smsAgreementApplicationDetailMapper.selectOne(new QueryWrapper<SmsAgreementApplicationDetail>()
                        .lambda()
                        .eq(SmsAgreementApplicationDetail::getApplicationId, application_id)
                        .eq(SmsAgreementApplicationDetail::getDetailSort, 1)
                        .orderByAsc(SmsAgreementApplicationDetail::getDetailSort));
        RangeTypeEnum rangeTypeEnum;
        if (firstDetail.getProcessObjectType() == AGREEMENT_OBJECT_TYPE_PERSON) {
            rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_PERSON;
        } else {
            rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_ROLE;
        }
        List<String> rangeList = new ArrayList<>();
        rangeList.add(firstDetail.getProcessObjectId());

        newTipsUtil.addNewTips(TipsTypeEnum.TIPS_TYPE_ENUM_ALLOW,
                user_id,
                rangeTypeEnum,
                rangeList,
                COPY_TYPE_ENUM_NONE,
                null,
                AppTypeEnum.APP_TYPE_ENUM_AGREEMENT_APPLICATION,
                application_id,
                null,
                null,
                firstDetail.getId(),
                null,
                null,
                null,
                applicationVO.getMessageTitle());
        return CommonResult.success();

    }

    @Override
    public ResponseResult updateAgreement(SmsAgreementApplicationVO applicationVO, String user_id) {
        //查看审批表是否存在且是否为本人
        SmsAgreementApplication paymentExamine =
                smsAgreementApplicationMapper.selectOne(new QueryWrapper<SmsAgreementApplication>()
                        .lambda()
                        .eq(SmsAgreementApplication::getId, applicationVO.getApplyId())
                        .eq(SmsAgreementApplication::getApplicationApplyUserId, user_id));
        if (paymentExamine == null || isNullOrEmpty(paymentExamine.getId())) {
            return CommonResult.failed(CommonCodeEnum.AGREEMENT_NOT_EXIST);
        }
        if (paymentExamine.getAllowStatus() != AGREEMENT_STATUS_WAIT_ALLOW) {
            return CommonResult.failed(CommonCodeEnum.AGREEMENT_CANCEL_FAIL_ALLOWED);
        }
        //修改校验审批节点未审批
        List<SmsAgreementApplicationDetail> detailList = smsAgreementApplicationDetailMapper.selectList(new LambdaQueryWrapper<SmsAgreementApplicationDetail>()
                .eq(SmsAgreementApplicationDetail::getApplicationId, applicationVO.getApplyId())
        .eq(SmsAgreementApplicationDetail::getDetailSort,1));
        if (detailList.isEmpty()) {
            return CommonResult.failed(CommonCodeEnum.AGREEMENT_PROCESS_NOT_EXIST);
        }
        SmsAgreementApplicationDetail smsAgreementApplicationDetail = detailList.get(0);
        if (smsAgreementApplicationDetail.getDetailAllowStatus() != AGREEMENT_STATUS_WAIT_ALLOW) {
            return CommonResult.failed(CommonCodeEnum.AGREEMENT_UPDATE_FAIL_ALLOWED);
        }
        //修改申请表
        BeanUtils.copyProperties(applicationVO, paymentExamine);
        smsAgreementApplicationMapper.updateById(paymentExamine);

        return CommonResult.success();

    }

    @Transactional
    @Override
    public ResponseResult cancelAgreement(SmsAgreementApplicationCancelVO cancelVO, String user_id) {
        if (isNullOrEmpty(cancelVO.getApplyId())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        //查看审批表是否存在且是否为本人
        SmsAgreementApplication paymentExamine =
                smsAgreementApplicationMapper.selectOne(new QueryWrapper<SmsAgreementApplication>()
                        .lambda()
                        .eq(SmsAgreementApplication::getId, cancelVO.getApplyId())
                        .eq(SmsAgreementApplication::getApplicationApplyUserId, user_id));
        if (paymentExamine == null || isNullOrEmpty(paymentExamine.getId())) {
            return CommonResult.failed(CommonCodeEnum.AGREEMENT_NOT_EXIST);
        }
        if (paymentExamine.getAllowStatus() != AGREEMENT_STATUS_WAIT_ALLOW) {
            return CommonResult.failed(CommonCodeEnum.AGREEMENT_CANCEL_FAIL_ALLOWED);
        }
        //判断是否审批中
//        List<SmsAgreementApplicationDetail> detailList =
//                smsAgreementApplicationDetailMapper.selectList(new QueryWrapper<SmsAgreementApplicationDetail>()
//                        .lambda()
//                        .eq(SmsAgreementApplicationDetail::getApplicationId, cancelVO.getApplyId())
//                        .eq(SmsAgreementApplicationDetail::getDetailAllowStatus, AGREEMENT_STATUS_PASS));
//        if (detailList != null && detailList.size() > 0) {
//            return CommonResult.failed(CommonCodeEnum.AGREEMENT_CANCEL_FAIL_ALLOWING);
//        }

        //撤回审批
        SmsAgreementApplication cancelExamine = new SmsAgreementApplication();
        cancelExamine.setId(cancelVO.getApplyId());
        cancelExamine.setAllowStatus(AGREEMENT_STATUS_CANCEL);
        cancelExamine.setEndTime(new Date());
        smsAgreementApplicationMapper.updateById(cancelExamine);

        //修改节点状态
        SmsAgreementApplicationDetail cancelExamineDetail = new SmsAgreementApplicationDetail();
        cancelExamineDetail.setDetailAllowStatus(AGREEMENT_STATUS_CANCEL);

        smsAgreementApplicationDetailMapper.update(cancelExamineDetail, new QueryWrapper<SmsAgreementApplicationDetail>()
                .lambda()
                .eq(SmsAgreementApplicationDetail::getApplicationId, cancelVO.getApplyId())
                .eq(SmsAgreementApplicationDetail::getDetailAllowStatus,AGREEMENT_STATUS_WAIT_ALLOW));

        //消息通知
        newTipsUtil.cancelFinishTips(cancelVO.getApplyId());

        return CommonResult.success();
    }

    @Transactional
    @Override
    public ResponseResult allowAgreement(SmsAgreementApplicationAllowVO allowVO, String user_id) {
        if (isNullOrEmpty(allowVO.getApplyId()) || isNullOrEmpty(allowVO.getDetailId())
                || isNullOrEmpty(allowVO.getDetailAllowStatus())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        if (allowVO.getDetailAllowStatus() != AGREEMENT_STATUS_PASS
                && allowVO.getDetailAllowStatus() != AGREEMENT_STATUS_DENY) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        SmsAgreementApplicationDetail paymentExamineDetail =
                smsAgreementApplicationDetailMapper.selectOne(new QueryWrapper<SmsAgreementApplicationDetail>()
                        .lambda()
                        .eq(SmsAgreementApplicationDetail::getApplicationId, allowVO.getApplyId())
                        .eq(SmsAgreementApplicationDetail::getId, allowVO.getDetailId())
                        .eq(SmsAgreementApplicationDetail::getDetailAllowStatus, AGREEMENT_STATUS_WAIT_ALLOW));
        if (paymentExamineDetail == null || isNullOrEmpty(paymentExamineDetail.getId())) {
            return CommonResult.failed(CommonCodeEnum.AGREEMENT_ALLOW_FAIL);
        }

        //判断该节点是否本人审批（防止跳节点审批）
        if (paymentExamineDetail.getProcessObjectType() == AGREEMENT_OBJECT_TYPE_PERSON) {
            if (!paymentExamineDetail.getProcessObjectId().equals(user_id)) {
                return CommonResult.failed(CommonCodeEnum.AGREEMENT_ALLOW_FAIL);
            }

        } else {
            List<String> roleList = cacheUtil.getRoleList(user_id);
            List<String> filterRoleList = roleList.stream().filter(role -> role.equals(paymentExamineDetail.getProcessObjectId())).collect(Collectors.toList());
            if (filterRoleList.size() < 1) {
                return CommonResult.failed(CommonCodeEnum.PAYMENT_ALLOW_FAIL);
            }
        }

        if (!paymentExamineDetail.getDetailSort().equals(1)) {
            SmsAgreementApplicationDetail preDetail =
                    smsAgreementApplicationDetailMapper.selectOne(new QueryWrapper<SmsAgreementApplicationDetail>()
                            .lambda()
                            .eq(SmsAgreementApplicationDetail::getApplicationId, allowVO.getApplyId())
                            .eq(SmsAgreementApplicationDetail::getDetailSort, paymentExamineDetail.getDetailSort() - 1));
            if (preDetail != null && isNullOrEmpty(preDetail.getId())) {
                if (preDetail.getDetailAllowStatus() != AGREEMENT_STATUS_PASS) {
                    return CommonResult.failed(CommonCodeEnum.AGREEMENT_ALLOW_FAIL);
                }
            }
        }


        SmsAgreementApplicationDetail allowDetail = new SmsAgreementApplicationDetail();
        allowDetail.setId(allowVO.getDetailId());
        allowDetail.setDetailAllowStatus(allowVO.getDetailAllowStatus());
        if (!isNullOrEmpty(allowVO.getDetailAllowOpinion())) {
            allowDetail.setDetailAllowOption(allowVO.getDetailAllowOpinion());
        }
        Date nowDate = new Date();
        allowDetail.setDetailAllowTime(nowDate);
        allowDetail.setDetailAllowUserId(user_id);

        if (paymentExamineDetail.getProcessIsSign()) {

            if(paymentExamineDetail.getProcessName().equals("后勤部")){
                allowDetail.setDetailAllowSign(allowVO.getDetailAllowSign());
            }else if (isNullOrEmpty(allowVO.getDetailAllowSign())) {
                ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.INVALID_PARAM));
            }

            allowDetail.setDetailAllowSign(allowVO.getDetailAllowSign());

        }
        if (paymentExamineDetail.getProcessIsStamp()) {
            if (isNullOrEmpty(allowVO.getDetailAllowStamp())) {
                ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.INVALID_PARAM));
            }
            allowDetail.setDetailAllowStamp(allowVO.getDetailAllowStamp());
        }
        smsAgreementApplicationDetailMapper.updateById(allowDetail);

        boolean is_done = false;

        //判断是否最后一个节点 是否驳回
        Integer detailCount = smsAgreementApplicationDetailMapper.selectCount(new QueryWrapper<SmsAgreementApplicationDetail>()
                .lambda()
                .eq(SmsAgreementApplicationDetail::getApplicationId, allowVO.getApplyId()));
        if (detailCount.equals(paymentExamineDetail.getDetailSort()) || allowVO.getDetailAllowStatus() == WORK_STATUS_DENY) {
            is_done = true;

            SmsAgreementApplication updateApplication = new SmsAgreementApplication();
            updateApplication.setId(allowVO.getApplyId());
            updateApplication.setEndTime(nowDate);
            updateApplication.setAllowStatus(allowVO.getDetailAllowStatus());
            smsAgreementApplicationMapper.updateById(updateApplication);
        }

        //节点驳回 重置其余节点状态
        if (allowVO.getDetailAllowStatus() == AGREEMENT_STATUS_DENY) {
            SmsAgreementApplicationDetail updateDenyDetail =
                    new SmsAgreementApplicationDetail();
            updateDenyDetail.setDetailAllowStatus(AGREEMENT_STATUS_DENY_FINISH);
            smsAgreementApplicationDetailMapper.update(updateDenyDetail, new QueryWrapper<SmsAgreementApplicationDetail>()
                    .lambda()
                    .eq(SmsAgreementApplicationDetail::getApplicationId, allowVO.getApplyId())
                    .eq(SmsAgreementApplicationDetail::getDetailAllowStatus, AGREEMENT_STATUS_WAIT_ALLOW));
        }


        //消息通知
        if (is_done) {
            boolean result_status = false;
            if (allowVO.getDetailAllowStatus() == AGREEMENT_STATUS_PASS) {
                result_status = true;
            }
            newTipsUtil.allowFinishTips(allowVO.getApplyId(), user_id, result_status);
        } else {
            SmsAgreementApplicationDetail nextDetail =
                    smsAgreementApplicationDetailMapper.selectOne(new QueryWrapper<SmsAgreementApplicationDetail>()
                            .lambda()
                            .eq(SmsAgreementApplicationDetail::getApplicationId, allowVO.getApplyId())
                            .eq(SmsAgreementApplicationDetail::getDetailSort, paymentExamineDetail.getDetailSort() + 1));
            RangeTypeEnum rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_PERSON;
            if (nextDetail.getProcessObjectType() == AGREEMENT_OBJECT_TYPE_ROLE) {
                rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_ROLE;
            }
            List<String> rangeIDList = new ArrayList<>();
            rangeIDList.add(nextDetail.getProcessObjectId());
            newTipsUtil.allowContinueTips(allowVO.getApplyId(),
                    user_id,
                    rangeTypeEnum,
                    rangeIDList,
                    nextDetail.getId());
        }
        return CommonResult.success();
    }

    @Override
    public ResponseResult getAgreementList(String search_str, Integer sort, Integer allowStatus, Integer pageSize, Integer pageNum, Integer apply_type, String user_id) {
        if (isNullOrEmpty(apply_type)) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        List<SmsAgreementApplicationDTO> respList = new ArrayList<>();
        int total = 0;

        if (apply_type == AGREEMENT_TYPE_APPLY) {
//            if (isNullOrEmpty(sort)) {
//                return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
//            }
            Page<SmsAgreementApplication> page = new Page<>(pageNum, pageSize);
            QueryWrapper<SmsAgreementApplication> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda()
                    .eq(SmsAgreementApplication::getApplicationApplyUserId, user_id);
            //排序方式 0:审批时间 1:审批状态
            if (!isNullOrEmpty(sort)) {
                if (sort == SORT_TYPE_TIME) {
                    queryWrapper.lambda().orderByDesc(SmsAgreementApplication::getCreateTime);
                } else if (sort == SORT_TYPE_ALLOW_STATUS) {
                    queryWrapper.lambda()
                            .orderByAsc(SmsAgreementApplication::getAllowStatus)
                            .orderByDesc(SmsAgreementApplication::getCreateTime);
                }
            }

            if (!isNullOrEmpty(search_str)) {
                queryWrapper.lambda().and(i ->
                        i.like(SmsAgreementApplication::getProjectUnit, search_str)
                                .or()
                                .like(SmsAgreementApplication::getProjectName, search_str)
                                .or()
                                .like(SmsAgreementApplication::getCooperationUnit, search_str));
            }
            if (!isNullOrEmpty(allowStatus)) {
                queryWrapper.lambda().eq(SmsAgreementApplication::getAllowStatus,allowStatus);
            }
            smsAgreementApplicationMapper.selectPage(page, queryWrapper);
            respList = page.getRecords()
                    .stream()
                    .map(smsExamine -> {
                        SmsAgreementApplicationDTO smsPaymentExamineResp =
                                new SmsAgreementApplicationDTO();
                        BeanUtils.copyProperties(smsExamine, smsPaymentExamineResp);
                        smsPaymentExamineResp.setApplyId(smsExamine.getId());

                        SmsUser smsUser = cacheUtil.getUserInfo(smsExamine.getApplicationApplyUserId());
                        SmsAgreementApplicationUserDTO smsExamineUserResp = new SmsAgreementApplicationUserDTO();
                        if (smsUser != null) {
                            BeanUtils.copyProperties(smsUser, smsExamineUserResp);
                        }
                        smsPaymentExamineResp.setApplyUserInfo(smsExamineUserResp);

                        return smsPaymentExamineResp;
                    })
                    .collect(Collectors.toList());
            total = (int) page.getTotal();
        }

        else if (apply_type == AGREEMENT_TYPE_ALLOWED) {

            Page<SmsAgreementApplicationMPJDTO> page = new Page<>(pageNum, pageSize);
            MPJLambdaWrapper<SmsAgreementApplicationDetail> mpjLambdaWrapper = new MPJLambdaWrapper<>();
            mpjLambdaWrapper.selectAll(SmsAgreementApplicationDetail.class)
                    .selectAll(SmsAgreementApplication.class)
                    .selectAs(SmsAgreementApplication::getCreateTime, "createTime")
                    .selectAs(SmsAgreementApplicationDetail::getId, "detailId")
                    .leftJoin(SmsAgreementApplication.class, SmsAgreementApplication::getId, SmsAgreementApplicationDetail::getApplicationId)
                    .eq(SmsAgreementApplicationDetail::getDetailAllowUserId, user_id)
                    //.orderByDesc(SmsAgreementApplication::getCreateTime)
                    .orderByDesc(SmsAgreementApplicationDetail::getDetailAllowTime)
            ;
            mpjLambdaWrapper.and(wrapper -> {
                wrapper.eq(SmsAgreementApplicationDetail::getDetailAllowStatus, AGREEMENT_STATUS_PASS)
                        .or()
                        .eq(SmsAgreementApplicationDetail::getDetailAllowStatus, AGREEMENT_STATUS_DENY);
            });
            if(!isNullOrEmpty(search_str)){
                List<String> userIds = smsUserMapper.selectList(new QueryWrapper<SmsUser>()
                        .lambda()
                        .like(SmsUser::getRealName, search_str))
                        .stream()
                        .map(SmsUser::getId).collect(Collectors.toList());

                mpjLambdaWrapper.and(queryWrapper ->{
                    queryWrapper.like(SmsAgreementApplication::getProjectUnit,search_str)
                            .or()
                            .like(SmsAgreementApplication::getCooperationUnit,search_str)
                            .or()
                            .like(SmsAgreementApplication::getProjectName,search_str);
                    if(userIds.size() > 0) {
                        queryWrapper.or().in(SmsAgreementApplication::getApplicationApplyUserId, userIds);
                    }
                });
            }

            smsAgreementApplicationMpjMapper.selectJoinPage(page, SmsAgreementApplicationMPJDTO.class, mpjLambdaWrapper);

            respList = page.getRecords()
                    .stream()
                    .map(smsApplicationMPJDTO -> {
                        SmsAgreementApplicationDTO smsApplicationDTO = new SmsAgreementApplicationDTO();
                        BeanUtils.copyProperties(smsApplicationMPJDTO, smsApplicationDTO);
                        smsApplicationDTO.setCreateTime(smsApplicationMPJDTO.getCreateTime());
                        smsApplicationDTO.setApplyId(smsApplicationMPJDTO.getApplicationId());
                        smsApplicationDTO.setProjectContractNum(smsApplicationMPJDTO.getProjectContractNum());
                        SmsUser applyUser = cacheUtil.getUserInfo(smsApplicationDTO.getApplicationApplyUserId());
                        SmsAgreementApplicationUserDTO userDTO = new SmsAgreementApplicationUserDTO();
                        if (applyUser != null) {
                            BeanUtils.copyProperties(applyUser, userDTO);
                        }
                        smsApplicationDTO.setApplyUserInfo(userDTO);

                        SmsUser allowUser = cacheUtil.getUserInfo(smsApplicationDTO.getDetailAllowUserId());
                        SmsAgreementApplicationUserDTO staffUserDTO = new SmsAgreementApplicationUserDTO();
                        if (allowUser != null) {
                            BeanUtils.copyProperties(allowUser, staffUserDTO);
                        }
                        smsApplicationDTO.setAllowUserInfo(staffUserDTO);

                        return smsApplicationDTO;
                    })
                    .collect(Collectors.toList());
            total = (int) page.getTotal();

        } else if (apply_type == AGREEMENT_TYPE_ALLOW_WAIT_ME) {
            List<String> roleList = cacheUtil.getRoleList(user_id);

            //获取所有待审批申请流程节点
            List<SmsAgreementApplicationDetail> detailList
                    = smsAgreementApplicationDetailMapper.selectList(new QueryWrapper<SmsAgreementApplicationDetail>()
                    .lambda()
                    .eq(SmsAgreementApplicationDetail::getDetailAllowStatus, AGREEMENT_STATUS_WAIT_ALLOW)
                    );

            List<SmsAgreementApplicationDetail> filterDetailList = detailList.stream()
                    .filter(detail -> {
                        if (detail.getProcessIsApplicationEdit().equals(1)) {
                            if (!detail.getProcessObjectId().equals(user_id)) {
                                return false;
                            }
                        } else {
                            if (detail.getProcessObjectType() == PROCESS_PEOPLE_CHECK_TYPE) {
                                if (!detail.getProcessObjectId().equals(user_id)) {
                                    return false;
                                }
                            } else {
                                List<String> filterRoleList = roleList.stream().filter(role -> role.equals(detail.getProcessObjectId())).collect(Collectors.toList());
                                if (filterRoleList.size() < 1) {
                                    return false;
                                }
                            }

                        }

                        if (detail.getDetailSort().equals(1)) {
                            return true;
                        }
                        //判断上一个流程节点是否完成
                        SmsAgreementApplicationDetail preDetail =
                                smsAgreementApplicationDetailMapper.selectOne(new QueryWrapper<SmsAgreementApplicationDetail>()
                                        .lambda()
                                        .eq(SmsAgreementApplicationDetail::getApplicationId, detail.getApplicationId())
                                        .eq(SmsAgreementApplicationDetail::getDetailSort, detail.getDetailSort() - 1)
                                        .eq(SmsAgreementApplicationDetail::getDetailAllowStatus, AGREEMENT_STATUS_PASS));
                        if (preDetail == null || isNullOrEmpty(preDetail.getId())) {
                            return false;
                        }
                        return true;
                    })
                    .collect(Collectors.toList());
            if (filterDetailList.size() > 0) {
                List<String> detailIDList = filterDetailList.stream().map(SmsAgreementApplicationDetail::getId).collect(Collectors.toList());

                Page<SmsAgreementApplicationDetail> page = new Page<>(pageNum, pageSize);
                QueryWrapper<SmsAgreementApplicationDetail> queryWrapper = new QueryWrapper<>();
                queryWrapper.lambda()
                        .in(SmsAgreementApplicationDetail::getId, detailIDList)
                        .orderByDesc(SmsAgreementApplicationDetail::getCreateTime);

                smsAgreementApplicationDetailMapper.selectPage(page, queryWrapper);

                respList = page.getRecords()
                        .stream()
                        .map(smsApplicationDetail -> {
                            SmsAgreementApplication application
                                    = smsAgreementApplicationMapper.selectById(smsApplicationDetail.getApplicationId());
                            SmsAgreementApplicationDTO applicationDTO
                                    = new SmsAgreementApplicationDTO();
                            BeanUtils.copyProperties(application, applicationDTO);
                            applicationDTO.setApplyId(smsApplicationDetail.getApplicationId());

                            SmsUser applyUser = cacheUtil.getUserInfo(applicationDTO.getApplicationApplyUserId());
                            SmsAgreementApplicationUserDTO applicationUserDTO = new SmsAgreementApplicationUserDTO();
                            if (applyUser != null) {
                                BeanUtils.copyProperties(applyUser, applicationUserDTO);
                            }
                            applicationDTO.setApplyUserInfo(applicationUserDTO);

                            applicationDTO.setDetailId(smsApplicationDetail.getId());

                            return applicationDTO;
                        })
                        .filter(q -> {
                            if(!isNullOrEmpty(search_str)){
                                List<String> userIds = smsUserMapper.selectList(new QueryWrapper<SmsUser>()
                                        .lambda()
                                        .like(SmsUser::getRealName, search_str))
                                        .stream()
                                        .map(SmsUser::getId).collect(Collectors.toList());
                                if(q.getProjectUnit().contains(search_str)||q.getProjectName().contains(search_str) || q.getCooperationUnit().contains(search_str)
                                ||q.getProjectContractNum().contains(search_str)){
                                    return true;
                                }
                                if(userIds.size() > 0 && userIds.contains(q.getApplicationApplyUserId())) {
                                    return true;
                                }
//                                QueryWrapper<SmsAgreementApplication> queryWrapper1 = new QueryWrapper<>();
//                                queryWrapper1.lambda().eq(SmsAgreementApplication::getId,q.getApplicationId());
//                                queryWrapper1.lambda().and(w ->{
//                                    w.like(SmsAgreementApplication::getProjectUnit,search_str)
//                                            .or()
//                                            .like(SmsAgreementApplication::getProjectAmount,search_str)
//                                            .or()
//                                            .like(SmsAgreementApplication::getProjectContractNum,search_str);
//                                    if(userIds.size() > 0) {
//                                        w.or().in(SmsAgreementApplication::getApplicationApplyUserId, userIds);
//                                    }
                                return false;
                            }
                          return true;
                        })
                        .collect(Collectors.toList());

            }
        }
        return CommonResult.success(respList, respList.size());


    }


    @Override
    public ResponseResult getAgreementDetail(String apply_id, String user_id) {
        if (isNullOrEmpty(apply_id)) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        SmsAgreementApplication paymentExamine = smsAgreementApplicationMapper.selectById(apply_id);
        if (paymentExamine == null || isNullOrEmpty(paymentExamine.getId())) {
            return CommonResult.failed(CommonCodeEnum.AGREEMENT_NOT_EXIST);
        }

        SmsAgreementApplicationDTO paymentExamineResp = new SmsAgreementApplicationDTO();
        BeanUtils.copyProperties(paymentExamine, paymentExamineResp);
        paymentExamineResp.setApplyId(paymentExamine.getId());

        SmsUser smsUser = cacheUtil.getUserInfo(paymentExamineResp.getApplicationApplyUserId());
        SmsAgreementApplicationUserDTO smsExamineUserResp = new SmsAgreementApplicationUserDTO();
        if (smsUser != null) {
            BeanUtils.copyProperties(smsUser, smsExamineUserResp);
        }
        paymentExamineResp.setApplyUserInfo(smsExamineUserResp);

        List<SmsAgreementApplicationDetailDTO> detailRespList =
                smsAgreementApplicationDetailMapper.selectList(new QueryWrapper<SmsAgreementApplicationDetail>()
                        .lambda()
                        .eq(SmsAgreementApplicationDetail::getApplicationId, apply_id)
                        .orderByAsc(SmsAgreementApplicationDetail::getDetailSort))
                        .stream()
                        .map(detail -> {
                            SmsAgreementApplicationDetailDTO detailResp = new SmsAgreementApplicationDetailDTO();
                            BeanUtils.copyProperties(detail, detailResp);
                            detailResp.setDetailAllowOpinion(detail.getDetailAllowOption());
                            if(detailResp.getProcessObjectType()==AGREEMENT_OBJECT_TYPE_PERSON){
                                SmsUser smsUser1 = smsUserMapper.selectById(detailResp.getProcessObjectId());
                                if(!isNullOrEmpty(smsUser1)) {
                                    detailResp.setRealName(smsUser1.getRealName());
                                    detailResp.setHeadPic(smsUser1.getUserPic());
                                }
                            }
                            else if(detailResp.getProcessObjectType()==AGREEMENT_OBJECT_TYPE_ROLE){
                                SmsRole smsRole = smsRoleMapper.selectById(detailResp.getProcessObjectId());
                                if(!isNullOrEmpty(smsRole)) {
                                    detailResp.setRealName(smsRole.getRoleName());
                                }
                            }
                            if (!isNullOrEmpty(detailResp.getDetailAllowUserId())) {
                                SmsUser userInfo = cacheUtil.getUserInfo(detailResp.getDetailAllowUserId());
                                SmsAgreementApplicationUserDTO paymentExamineUserResp = new SmsAgreementApplicationUserDTO();
                                if (userInfo != null) {
                                    BeanUtils.copyProperties(userInfo, paymentExamineUserResp);
                                }
                                detailResp.setAllowUserInfo(paymentExamineUserResp);
                            }
                            return detailResp;
                        })
                        .collect(Collectors.toList());
        paymentExamineResp.setDetailList(detailRespList);
        return CommonResult.success(paymentExamineResp);
    }

    @Override
    public ResponseResult getAgreementApplicationOriginSettingProcess() {
        List<SmsAgreementApplicationOriginSettingProcessDTO> respList =
                smsAgreementApplicationProcessMapper.selectList(new QueryWrapper<SmsAgreementApplicationProcess>()
                        .lambda()
                        .eq(SmsAgreementApplicationProcess::getProcessIsApplicationEdit, true)
                        .eq(SmsAgreementApplicationProcess::getProcessIsUse,true)
                        .orderByAsc(SmsAgreementApplicationProcess::getProcessSort))
                        .stream()
                        .map(process -> {
                            SmsAgreementApplicationOriginSettingProcessDTO smsPaymentExamineOriginSettingProcessResp =
                                    new SmsAgreementApplicationOriginSettingProcessDTO();
                            BeanUtils.copyProperties(process, smsPaymentExamineOriginSettingProcessResp);
                            return smsPaymentExamineOriginSettingProcessResp;
                        })
                        .collect(Collectors.toList());
        return CommonResult.success(respList);
    }

    @Override
    public ResponseResult selectAllAgreementApply(String apply_unit, Integer pageSize, Integer pageNum, Integer status) {
        QueryWrapper<SmsAgreementApplication> queryWrapper = new QueryWrapper<>();
        if (!isNullOrEmpty(apply_unit)) {
            queryWrapper.lambda().like(SmsAgreementApplication::getProjectUnit, apply_unit);
        }
        if(!isNullOrEmpty(status)){
            queryWrapper.lambda().eq(SmsAgreementApplication::getAllowStatus,status);
        }
        queryWrapper.orderByDesc("create_time");
        Page<SmsAgreementApplication> page = new Page<>(pageNum, pageSize);
        List<SmsAgreementApplicationDTO> collect ;

        Page<SmsAgreementApplication> appApplicationPage = smsAgreementApplicationMapper.selectPage(page, queryWrapper);
        List<SmsAgreementApplication> records = appApplicationPage.getRecords();
        collect = records.stream().map(appApplication -> {
            SmsAgreementApplicationDTO appApplicationResp = new SmsAgreementApplicationDTO();
            BeanUtils.copyProperties(appApplication, appApplicationResp);
            SmsUser smsUser = cacheUtil.getUserInfo(appApplicationResp.getApplicationApplyUserId());
            if (smsUser != null) {
                SmsAgreementApplicationUserDTO user = new SmsAgreementApplicationUserDTO();
                BeanUtils.copyProperties(smsUser, user);
                appApplicationResp.setApplyUserInfo(user);
            }

            return appApplicationResp;
        }).collect(Collectors.toList());

        int total = (int) page.getTotal();
        return CommonResult.success(collect, total);
    }

    @Override
    @Async
    public Future<ResponseResult> tableDownload(String apply_id, HttpServletResponse response) {
        SmsAgreementApplication agreementApplication = smsAgreementApplicationMapper.selectById(apply_id);
        if (agreementApplication == null || agreementApplication.getId() == null) {
            return new AsyncResult<>(CommonResult.failed(CommonCodeEnum.AGREEMENT_NOT_EXIST));
        }
//        if (agreementApplication.getAllowStatus() == WORK_STATUS_WAIT_ALLOW) {
//            return new AsyncResult<>(CommonResult.failed(CommonCodeEnum.AGREEMENT_DOWNLOAD_FAIL));
//        }

        String OSName = System.getProperty("os.name");
        String filePath = OSName.toLowerCase().startsWith("win") ? fileSavePathConstant.getFILE_DOWNLOAD_PATH()
                : fileSavePathConstant.getFILE_DOWNLOAD_PATH_LINUX();

        String newFilePath = filePath + apply_id + ".docx";
        String pdfFilePath = filePath + apply_id + ".pdf";

        File pdfFile = new File(pdfFilePath);

     //   if (!pdfFile.exists()) {
            try {



                List<String> picTagList = new ArrayList<>();
                List<String> textTagList = new ArrayList<>();

                Map<String, Object> map = new HashMap<>();
                map.put("contractNum", agreementApplication.getProjectContractNum());
                map.put("projectUnit", agreementApplication.getProjectUnit());
                map.put("projectCheckTime", agreementApplication.getProjectCheckTime());
                map.put("projectName",agreementApplication.getProjectName());
                map.put("cooperationUnit", agreementApplication.getCooperationUnit());
                map.put("contacts", agreementApplication.getCooperationContacts());
                map.put("phone", agreementApplication.getCooperationPhone());
                map.put("reasonPursuant", agreementApplication.getReasonPursuant());
                map.put("projectAbstract", agreementApplication.getProjectAbstract());
                map.put("projectAmount", agreementApplication.getProjectAmount());
                map.put("projectTerm", agreementApplication.getProjectTerm());
                map.put("projectPayWay", agreementApplication.getProjectPayWay());
//                map.put("projectOpinion", agreementApplication.getProjectOpinion());
                map.put("createTime",TimeUtil.DateHanZiSimpleFormat(agreementApplication.getCreateTime()));

                textTagList.add("projectAbstract");
                //获取初始流程
                List<SmsAgreementApplicationProcess> processList = smsAgreementApplicationProcessMapper.selectList(new QueryWrapper<SmsAgreementApplicationProcess>()
                        .lambda()
                        .orderByAsc(SmsAgreementApplicationProcess::getProcessSort));
                if (processList == null || processList.size() < 1) {
                    return new AsyncResult<>(CommonResult.failed(CommonCodeEnum.FAIL));
                }

                //获取申请流程
                List<SmsAgreementApplicationDetail> detailList = smsAgreementApplicationDetailMapper.selectList(new QueryWrapper<SmsAgreementApplicationDetail>()
                        .lambda()
                        .eq(SmsAgreementApplicationDetail::getApplicationId, apply_id));
                for (SmsAgreementApplicationProcess process : processList) {
                    List<SmsAgreementApplicationDetail> filterDetail = detailList
                            .stream()
                            .filter(detail -> detail.getProcessId().equals(process.getId()))
                            .collect(Collectors.toList());
                    if (filterDetail.size() > 0) {
                        SmsAgreementApplicationDetail detail = filterDetail.get(0);
                        if (detail.getDetailAllowStatus() == EXAMINE_STATUS_PASS || detail.getDetailAllowStatus() == EXAMINE_STATUS_FORCED_FINISH) {
                            map.put("allowStatus" + process.getProcessSort() + "", "同意");
                        } else if (detail.getDetailAllowStatus() == EXAMINE_STATUS_DENY || detail.getDetailAllowStatus() == EXAMINE_STATUS_FORCED_REJECT) {
                            map.put("allowStatus" + process.getProcessSort() + "", "拒绝");
                        } else {
                            map.put("allowStatus" + process.getProcessSort() + "", "");
                        }

                        map.put("allowOption" + process.getProcessSort() + "", detail.getDetailAllowOption());

                        //添加签名
                        if (isNullOrEmpty(detail.getDetailAllowSign())) {
                            map.put("allowSign" + process.getProcessSort() + "", "");
                        } else {
                            String[] splitStr = detail.getDetailAllowSign().split("=");
                            String fileName = splitStr[splitStr.length - 1];

                            File file = new File(filePath + fileName);
                            if (file.exists()) {
                                InputStream inputStream = new FileInputStream(file);
                                PictureRenderData pictures = Pictures.ofStream(inputStream,
                                        PictureType.PNG).size(60, 60).create();

                                map.put("allowSign" + process.getProcessSort() + "", pictures);
                                picTagList.add("allowSign" + process.getProcessSort());
                            }
                        }

                        //添加印章
                        if (isNullOrEmpty(detail.getDetailAllowStamp())) {
                            map.put("allowStamp" + process.getProcessSort() + "", "");
                        } else {
                            String[] splitStr = detail.getDetailAllowStamp().split("=");
                            String fileName = splitStr[splitStr.length - 1];

                            File file = new File(filePath + fileName);
                            if (file.exists()) {
                                InputStream inputStream = new FileInputStream(file);
                                PictureRenderData pictures = Pictures.ofStream(inputStream,
                                        PictureType.PNG).size(60, 60).create();
                                map.put("allowStamp" + process.getProcessSort() + "", pictures);
                                picTagList.add("allowStamp" + process.getProcessSort());
                            }
                        }

                        //审批时间
                        if (isNullOrEmpty(detail.getDetailAllowTime())) {
                            map.put("detailAllowTime" + process.getProcessSort() + "", "");
                        } else {
                            map.put("detailAllowTime" + process.getProcessSort() + "", TimeUtil.DateHanZiSimpleFormat(detail.getDetailAllowTime()));
                        }
                    } else {
                        map.put("allowStatus" + process.getProcessSort() + "", "");
                        map.put("allowOption" + process.getProcessSort() + "", "");
                        map.put("allowSign" + process.getProcessSort() + "", "");
                        map.put("allowStamp" + process.getProcessSort() + "", "");
                        map.put("detailAllowTime" + process.getProcessSort() + "", "");
                    }
                }


                ClassPathResource resource = new ClassPathResource("applyTemplates/agreementApplication.docx");
                InputStream is = resource.getInputStream();
                FileOutputStream outputStream = new FileOutputStream(newFilePath);

                XWPFTemplate template = XWPFTemplate.compile(is);

                //配置图片标签
                Configure config = template.getConfig();
                for (String tag : picTagList
                ) {
                    config.customPolicy(tag, new PictureRenderPolicy());
                }

                //文字标签配置
                for (String textTag: textTagList) {
                    String tagContent = (String) map.get(textTag);
                    if (tagContent != null && tagContent.length() > 30){
                        Style style = new Style();
                        style.setFontSize(6.0);

                        TextRenderData data = new TextRenderData(tagContent,style);
                        map.put(textTag,data);
                    }
                }

                template.render(map);

                template.write(outputStream);

                is.close();
                outputStream.close();
                template.close();

                //word转pdf
                File destOri = new File(newFilePath);
                FileInputStream fileInputStream = new FileInputStream(destOri);
                FileOutputStream fileOutputStream = new FileOutputStream(pdfFilePath);

                Document document = new Document();
                document.loadFromStream(fileInputStream, FileFormat.Docx);
                //保存为PDF
                document.saveToFile(pdfFilePath, FileFormat.PDF);


                fileInputStream.close();
                fileOutputStream.close();
                document.close();

                log.debug("文件生成完成!");
            } catch (Exception e) {
                e.printStackTrace();
                return new AsyncResult<>(CommonResult.failed(CommonCodeEnum.FAIL));
            }
     //   }
        try {
            // 加载PDF文档
            PDDocument doc = PDDocument.load(pdfFile);
            doc.setAllSecurityToBeRemoved(true);
            // 创建水印
            String watermark = "四川东方教育集团";
            PDPageContentStream contentStream;

            for (PDPage page : doc.getPages()) {
                contentStream = new PDPageContentStream(doc, page, PDPageContentStream.AppendMode.APPEND, true, true);

                //加载字体
                ClassPathResource resource = new ClassPathResource("fonts/123.ttf");
                InputStream is = resource.getInputStream();
                PDFont font = PDType0Font.load(doc, is);


                int startX = 0; // 起始位置 x 坐标
                int startY = 0; // 起始位置 y 坐标
                float angle = -45; // 角度
                float interval = 330; // 间隔
                float opacity = 0.3f; // 透明度
                int colorR = 127; // 颜色 red 值
                int colorG = 127; // 颜色 green 值
                int colorB = 127; // 颜色 blue 值

                //透明的
                PDExtendedGraphicsState r0 = new PDExtendedGraphicsState();
                r0.setNonStrokingAlphaConstant(opacity);
                r0.setAlphaSourceFlag(true);
                contentStream.setGraphicsStateParameters(r0);

                //水印颜色
                contentStream.setNonStrokingColor(colorR, colorG, colorB);
                contentStream.beginText();
                contentStream.setFont(font, 30f);

                int x_times = (int) Math.ceil(page.getMediaBox().getWidth() / interval);
                int y_times = (int) Math.ceil(page.getMediaBox().getHeight() / interval);
                for (int x = startX; x <= x_times; x++) {
                    for (int y = startY; y <= y_times; y++) {
                        contentStream.setTextRotation(angle, (x * interval), (y * interval));
                        contentStream.showText(watermark);
                    }
                }
                contentStream.endText();
                contentStream.restoreGraphicsState();
                contentStream.close();
                is.close();
            }

//            response.reset();
            response.setCharacterEncoding("utf-8");
            response.setContentType("application/vnd.pdf;charset=utf-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("合同协议请示单预览.pdf", "utf-8"));
            response.setHeader("file-name", URLEncoder.encode("合同协议请示单预览.pdf", "utf-8"));
            response.setHeader("file-type","download");
            response.setHeader("Access-Control-Expose-Headers", "file-type,file-name");
            //刷新缓冲
            response.flushBuffer();

            // 保存PDF文档
            doc.save(response.getOutputStream());
            doc.close();
        } catch (Exception e) {
            e.printStackTrace();
            return new AsyncResult<>(CommonResult.failed(CommonCodeEnum.FAIL));

        }
        return null;
    }

    @Override
    @Async
    public Future<ResponseResult> exportAgreement(SmsAgreementExportVO smsAgreementExportVO, HttpServletResponse response) {
        if (isNullOrEmpty(smsAgreementExportVO.getIsExportProcess())) {
            return new AsyncResult<>(CommonResult.failed(CommonCodeEnum.INVALID_PARAM));
        }
        try {
            QueryWrapper<SmsAgreementApplication> queryWrapper = new QueryWrapper<>();

            if (!isNullOrEmpty(smsAgreementExportVO.getProjectUnit())) {
                queryWrapper.lambda().like(SmsAgreementApplication::getProjectUnit, smsAgreementExportVO.getProjectUnit());
            }

            queryWrapper.lambda().orderByDesc(SmsAgreementApplication::getCreateTime);
            List<SmsAgreementApplication> list = smsAgreementApplicationMapper.selectList(queryWrapper);
            //表头数据
            String[] header = smsAgreementExportVO.getLimitColumn().toArray(new String[0]);
            double sheetNum;
            //声明一个工作簿
            HSSFWorkbook workbook = new HSSFWorkbook();
            if (list != null && list.size() > 0) {
                sheetNum = Math.ceil((double) list.size() / StudentInfoCommonConstant.PER_SHEET_NUM);
                for (int k = 0; k < sheetNum; k++) {
                    //生成一个表格，设置表格名称为"资源导出表"
                    HSSFSheet sheet = workbook.createSheet("合同协议会审记录导出表" + (k + 1));

                    //设置表格列宽度为10个字节
                    sheet.setDefaultColumnWidth(12);
                    //创建标题的显示样式
                    HSSFCellStyle headerStyle = workbook.createCellStyle();
                    headerStyle.setFillForegroundColor(IndexedColors.YELLOW.index);
                    headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);

                    HSSFFont f = workbook.createFont();
                    f.setFontHeightInPoints((short) 10);//字号
                    f.setBold(true);//加粗
                    headerStyle.setFont(f);
                    //创建第一行表头
                    HSSFRow headrow = sheet.createRow(0);

                    //遍历添加表头(下面模拟遍历学生，也是同样的操作过程)
                    for (int i = 0; i < header.length + 1; i++) {
                        //创建一个单元格
                        HSSFCell cell = headrow.createCell(i);

                        if (i == 0) {
                            //创建一个内容对象
                            HSSFRichTextString text = new HSSFRichTextString("序号");
                            //将内容对象的文字内容写入到单元格中
                            cell.setCellValue(text);
                            cell.setCellStyle(headerStyle);
                            continue;
                        }
                        //创建一个内容对象
                        String header1 = apiModelUtil.getFieldValueByFieldName(SmsAgreementApplication.class, header[i - 1]);
                        HSSFRichTextString text = new HSSFRichTextString(header1);

                        //将内容对象的文字内容写入到单元格中
                        cell.setCellValue(text);
                        cell.setCellStyle(headerStyle);
                    }

                    //判断是否需要添加流程表头
                    if (smsAgreementExportVO.getIsExportProcess() == EXPORT_PROCESS_TRUE) {
                        List<SmsAgreementApplicationProcess> processList =
                                smsAgreementApplicationProcessMapper.selectList(new QueryWrapper<>());
                        if (processList != null && processList.size() > 0) {
                            Integer origin_num = header.length + 1;
                            for (SmsAgreementApplicationProcess process : processList) {
                                String process_name = process.getProcessName();
                                addProcessTableHead(headrow, headerStyle, origin_num, process_name);
                                origin_num += 4;
                            }
                        }
                    }

                    int range = StudentInfoCommonConstant.PER_SHEET_NUM;
                    if (k + 1 == sheetNum) {
                        range = list.size() - (StudentInfoCommonConstant.PER_SHEET_NUM) * k;
                    }
                    for (int i = 0; i < range; i++) {
                        //创建一行
                        HSSFRow row1 = sheet.createRow(i + 1);
                        SmsAgreementApplication checkInApplication = list.get((StudentInfoCommonConstant.PER_SHEET_NUM) * k + i);
                        Map map = JSONObject.parseObject(JSON.toJSONString(checkInApplication), Map.class);
                        row1.createCell(0).setCellValue(new HSSFRichTextString(i + 1 + ""));
                        for (int j = 0; j < header.length; j++) {
                            String rowContent = "";
                            if (map.get(header[j]) instanceof Long) {
                                rowContent = TimeUtil.DateformatTimestamp((long) map.get(header[j]));
                            } else if(map.get(header[j]) instanceof Integer) {
                                rowContent = String.valueOf(map.get(header[j]));
                            }else {
                                if (header[j].equals("applicationApplyUserId")) {
                                    SmsUser smsUser = cacheUtil.getUserInfo(checkInApplication.getApplicationApplyUserId());
                                    if (smsUser != null) {
                                        rowContent = smsUser.getRealName();
                                    } else {
                                        rowContent = "";
                                    }
                                } else {
                                    rowContent = (String) map.get(header[j]);
                                }
                            }
                            row1.createCell(j + 1).setCellValue(new HSSFRichTextString(rowContent));
                        }

                        if (smsAgreementExportVO.getIsExportProcess() == EXPORT_PROCESS_TRUE) {
                            List<SmsAgreementApplicationProcess> processList =
                                    smsAgreementApplicationProcessMapper.selectList(new QueryWrapper<>());
                            if (processList != null && processList.size() > 0) {
                                Integer origin_num = header.length + 1;
                                for (SmsAgreementApplicationProcess process : processList) {
                                    SmsAgreementApplicationDetail detail =
                                            smsAgreementApplicationDetailMapper.selectOne(new QueryWrapper<SmsAgreementApplicationDetail>()
                                                    .lambda()
                                                    .eq(SmsAgreementApplicationDetail::getApplicationId, checkInApplication.getId())
                                                    .eq(SmsAgreementApplicationDetail::getProcessId, process.getId()));
                                    if (detail == null || detail.getId() == null) {
                                        origin_num += 4;
                                    } else {
                                        //审批人
                                        SmsUser user = cacheUtil.getUserInfo(detail.getDetailAllowUserId());
                                        if (user == null) {
                                            row1.createCell(origin_num++).setCellValue(new HSSFRichTextString(""));
                                        } else {
                                            row1.createCell(origin_num++).setCellValue(new HSSFRichTextString(user.getRealName()));
                                        }

                                        //审批时间
                                        Date allow_time = detail.getDetailAllowTime();
                                        if (allow_time == null) {
                                            row1.createCell(origin_num++).setCellValue(new HSSFRichTextString(""));
                                        } else {
                                            row1.createCell(origin_num++).setCellValue(new HSSFRichTextString(TimeUtil.DateHanZiSimpleFormat(allow_time)));
                                        }

                                        //审批状态
                                        Integer allow_status = detail.getDetailAllowStatus();
                                        if (allow_status == EXAMINE_STATUS_PASS || allow_status == EXAMINE_STATUS_FORCED_FINISH) {
                                            row1.createCell(origin_num++).setCellValue(new HSSFRichTextString("同意"));
                                        } else if (allow_status == EXAMINE_STATUS_DENY || allow_status == EXAMINE_STATUS_FORCED_REJECT) {
                                            row1.createCell(origin_num++).setCellValue(new HSSFRichTextString("拒绝"));
                                        } else {
                                            row1.createCell(origin_num++).setCellValue(new HSSFRichTextString(""));
                                        }

                                        //审批意见
                                        String allow_option = detail.getDetailAllowOption();
                                        if (isNullOrEmpty(allow_option)) {
                                            row1.createCell(origin_num++).setCellValue(new HSSFRichTextString(""));
                                        } else {
                                            row1.createCell(origin_num++).setCellValue(new HSSFRichTextString(allow_option));
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

//            response.reset();
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("合同协议会审记录导出表.xlsx", "utf-8"));
            response.setCharacterEncoding("utf-8");
            response.setHeader("file-type", "download");
            response.setHeader("file-name", URLEncoder.encode("合同协议会审记录导出表.xlsx", "utf-8"));
            response.setHeader("Access-Control-Expose-Headers", "file-type,file-name");
//            //刷新缓冲
            response.flushBuffer();
            //workbook将Excel写入到response的输出流中，供页面下载
            OutputStream os = response.getOutputStream();
            workbook.write(os);

            workbook.close();
            os.close();
        } catch (Exception e) {
            e.printStackTrace();
            return new AsyncResult<>(CommonResult.failed(CommonCodeEnum.FAIL));
        }
        return null;
    }


    private void addProcessTableHead(HSSFRow headRow, HSSFCellStyle headerStyle, Integer origin_cell_num, String originHeadContent) {
        Integer cell_num = origin_cell_num;

        setTableHead(headRow, headerStyle, cell_num++, originHeadContent + "审批人");
        setTableHead(headRow, headerStyle, cell_num++, originHeadContent + "审批时间");
        setTableHead(headRow, headerStyle, cell_num++, originHeadContent + "审批状态");
        setTableHead(headRow, headerStyle, cell_num, originHeadContent + "审批意见");

    }
    private void setTableHead(HSSFRow headRow, HSSFCellStyle headerStyle, Integer cell_num, String headContent) {
        HSSFCell cell = headRow.createCell(cell_num);
        //创建一个内容对象
        HSSFRichTextString text = new HSSFRichTextString(headContent);

        //将内容对象的文字内容写入到单元格中
        cell.setCellValue(text);
        cell.setCellStyle(headerStyle);
    }

    @Override
    @Transactional
    public ResponseResult forcedFinishAgreementApplication(String applyId, String userId) {
        //校验数据
        if (isNullOrEmpty(applyId)) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        SmsAgreementApplication smsAgreementApplication = smsAgreementApplicationMapper.selectById(applyId);
        if(isNullOrEmpty(smsAgreementApplication)){
            return CommonResult.failed(CommonCodeEnum.AGREEMENT_NOT_EXIST);
        }
        if(smsAgreementApplication.getAllowStatus() != AGREEMENT_STATUS_WAIT_ALLOW){
            return CommonResult.failed(CommonCodeEnum.AGREEMENT_NOT_FORCED);
        }
        //修改审批表状态为通过
        smsAgreementApplication.setAllowStatus(AGREEMENT_STATUS_PASS);
        smsAgreementApplication.setEndTime(new Date());
        smsAgreementApplicationMapper.updateById(smsAgreementApplication);

        //修改节点为强制归档
        SmsAgreementApplicationDetail smsWorkApplicationDetail = new SmsAgreementApplicationDetail();
        smsWorkApplicationDetail.setDetailAllowStatus(AGREEMENT_STATUS_FORCED_FINISH);
        smsWorkApplicationDetail.setDetailAllowUserId(userId);
        smsWorkApplicationDetail.setDetailAllowTime(new Date());
        smsAgreementApplicationDetailMapper.update(smsWorkApplicationDetail,new LambdaQueryWrapper<SmsAgreementApplicationDetail>()
                .eq(SmsAgreementApplicationDetail::getApplicationId,applyId)
                .eq(SmsAgreementApplicationDetail::getDetailAllowStatus,AGREEMENT_STATUS_WAIT_ALLOW));

        //消息通知
        newTipsUtil.cancelFinishTips(applyId);

        return CommonResult.success();
    }

    @Override
    @Transactional
    public ResponseResult forcedTorsionAgreementApplication(SmsAgreementApplicationDetailTorsionVO torsionVO) {
        if(isNullOrEmpty(torsionVO.getDetailId(),torsionVO.getApplyId(),torsionVO.getProcessObjectType(),torsionVO.getProcessObjectId())){
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        //校验申请表 节点表
        SmsAgreementApplication smsAgreementApplication = smsAgreementApplicationMapper.selectById(torsionVO.getApplyId());
        if(isNullOrEmpty(smsAgreementApplication)){
            return CommonResult.failed(CommonCodeEnum.AGREEMENT_NOT_EXIST);
        }
        SmsAgreementApplicationDetail smsAgreementApplicationDetail = smsAgreementApplicationDetailMapper.selectById(torsionVO.getDetailId());
        if(isNullOrEmpty(smsAgreementApplicationDetail)){
            return CommonResult.failed(CommonCodeEnum.AGREEMENT_DETAIL_NOT_FORCED);
        }
        //只有待审批才能强制流转
        if(smsAgreementApplicationDetail.getDetailAllowStatus() != AGREEMENT_STATUS_WAIT_ALLOW){
            return CommonResult.failed(CommonCodeEnum.AGREEMENT_NOT_TORSION);
        }
        smsAgreementApplicationDetail.setProcessObjectType(torsionVO.getProcessObjectType());
        smsAgreementApplicationDetail.setProcessObjectId(torsionVO.getProcessObjectId());
        smsAgreementApplicationDetailMapper.updateById(smsAgreementApplicationDetail);
        //消息通知
        //判断第一节点直接发消息,其他要前节点审批后才发该节点通知
        boolean flag = true;
        if(!smsAgreementApplicationDetail.getDetailSort().equals(1)){
            SmsAgreementApplicationDetail beforeDetail = smsAgreementApplicationDetailMapper.selectOne(new LambdaQueryWrapper<SmsAgreementApplicationDetail>()
                    .eq(SmsAgreementApplicationDetail::getApplicationId, torsionVO.getApplyId())
                    .eq(SmsAgreementApplicationDetail::getDetailSort, smsAgreementApplicationDetail.getDetailSort() - 1));
            if(beforeDetail.getDetailAllowStatus() != AGREEMENT_STATUS_PASS){
               flag = false;
            }
        }
        if(flag) {
            RangeTypeEnum rangeTypeEnum;
            if (smsAgreementApplicationDetail.getProcessObjectType() == AGREEMENT_OBJECT_TYPE_PERSON) {
                rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_PERSON;
            } else {
                rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_ROLE;
            }
            List<String> rangeList = new ArrayList<>();
            rangeList.add(smsAgreementApplicationDetail.getProcessObjectId());
            newTipsUtil.allowContinueTips(torsionVO.getApplyId(),
                    null,
                    rangeTypeEnum,
                    rangeList,
                    smsAgreementApplicationDetail.getId());
        }
        return CommonResult.success();
    }

    @Override
    @Transactional
    public ResponseResult replaceApplyAgreementApplication(String userId, SmsAgreementApplicationAllowVO allowVO) {
        if (isNullOrEmpty(allowVO.getApplyId()) || isNullOrEmpty(allowVO.getDetailId())
                || isNullOrEmpty(allowVO.getDetailAllowStatus())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        if (allowVO.getDetailAllowStatus() != AGREEMENT_STATUS_PASS
                && allowVO.getDetailAllowStatus() != AGREEMENT_STATUS_DENY) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        SmsAgreementApplicationDetail paymentExamineDetail =
                smsAgreementApplicationDetailMapper.selectOne(new QueryWrapper<SmsAgreementApplicationDetail>()
                        .lambda()
                        .eq(SmsAgreementApplicationDetail::getApplicationId, allowVO.getApplyId())
                        .eq(SmsAgreementApplicationDetail::getId, allowVO.getDetailId())
                        .eq(SmsAgreementApplicationDetail::getDetailAllowStatus, AGREEMENT_STATUS_WAIT_ALLOW));
        if (paymentExamineDetail == null || isNullOrEmpty(paymentExamineDetail.getId())) {
            return CommonResult.failed(CommonCodeEnum.AGREEMENT_ALLOW_FAIL);
        }


        if (!paymentExamineDetail.getDetailSort().equals(1)) {
            SmsAgreementApplicationDetail preDetail =
                    smsAgreementApplicationDetailMapper.selectOne(new QueryWrapper<SmsAgreementApplicationDetail>()
                            .lambda()
                            .eq(SmsAgreementApplicationDetail::getApplicationId, allowVO.getApplyId())
                            .eq(SmsAgreementApplicationDetail::getDetailSort, paymentExamineDetail.getDetailSort() - 1));
            if (preDetail != null && !isNullOrEmpty(preDetail.getId())) {
                if (preDetail.getDetailAllowStatus() != AGREEMENT_STATUS_PASS) {
                    return CommonResult.failed(CommonCodeEnum.AGREEMENT_ALLOW_FAIL);
                }
            }
        }


        SmsAgreementApplicationDetail allowDetail = new SmsAgreementApplicationDetail();
        allowDetail.setId(allowVO.getDetailId());
        allowDetail.setDetailAllowStatus(allowVO.getDetailAllowStatus());
        if (!isNullOrEmpty(allowVO.getDetailAllowOpinion())) {
            allowDetail.setDetailAllowOption(allowVO.getDetailAllowOpinion());
        }
        Date nowDate = new Date();
        allowDetail.setDetailAllowTime(nowDate);
        allowDetail.setDetailAllowUserId(userId);

        if (paymentExamineDetail.getProcessName().equals("后勤部")) {
            allowDetail.setDetailAllowSign(allowVO.getDetailAllowSign());
        }

        allowDetail.setDetailAllowSign(allowVO.getDetailAllowSign());
        allowDetail.setDetailAllowStamp(allowVO.getDetailAllowStamp());
        smsAgreementApplicationDetailMapper.updateById(allowDetail);

        boolean is_done = false;

        //判断是否最后一个节点 是否驳回
        Integer detailCount = smsAgreementApplicationDetailMapper.selectCount(new QueryWrapper<SmsAgreementApplicationDetail>()
                .lambda()
                .eq(SmsAgreementApplicationDetail::getApplicationId, allowVO.getApplyId()));
        if (detailCount.equals(paymentExamineDetail.getDetailSort()) || allowVO.getDetailAllowStatus() == WORK_STATUS_DENY) {
            is_done = true;

            SmsAgreementApplication updateApplication = new SmsAgreementApplication();
            updateApplication.setId(allowVO.getApplyId());
            updateApplication.setEndTime(nowDate);
            updateApplication.setAllowStatus(allowVO.getDetailAllowStatus());
            smsAgreementApplicationMapper.updateById(updateApplication);
        }

        //节点驳回 重置其余节点状态
        if (allowVO.getDetailAllowStatus() == WORK_STATUS_DENY) {
            SmsAgreementApplicationDetail updateDenyDetail =
                    new SmsAgreementApplicationDetail();
            updateDenyDetail.setDetailAllowStatus(WORK_STATUS_DENY_FINISH);
            smsAgreementApplicationDetailMapper.update(updateDenyDetail, new QueryWrapper<SmsAgreementApplicationDetail>()
                    .lambda()
                    .eq(SmsAgreementApplicationDetail::getApplicationId, allowVO.getApplyId())
                    .eq(SmsAgreementApplicationDetail::getDetailAllowStatus, WORK_STATUS_WAIT_ALLOW));
        }

        //节点驳回 重置其余节点状态
        if (allowVO.getDetailAllowStatus() == AGREEMENT_STATUS_DENY) {
            SmsAgreementApplicationDetail updateDenyDetail =
                    new SmsAgreementApplicationDetail();
            updateDenyDetail.setDetailAllowStatus(AGREEMENT_STATUS_DENY_FINISH);
            smsAgreementApplicationDetailMapper.update(updateDenyDetail, new QueryWrapper<SmsAgreementApplicationDetail>()
                    .lambda()
                    .eq(SmsAgreementApplicationDetail::getApplicationId, allowVO.getApplyId())
                    .eq(SmsAgreementApplicationDetail::getDetailAllowStatus, AGREEMENT_STATUS_WAIT_ALLOW));
        }

        //消息通知
        if (is_done) {
            boolean result_status = false;
            if (allowVO.getDetailAllowStatus() == AGREEMENT_STATUS_PASS) {
                result_status = true;
            }
            newTipsUtil.allowFinishTips(allowVO.getApplyId(), userId, result_status);
        } else {
            SmsAgreementApplicationDetail nextDetail =
                    smsAgreementApplicationDetailMapper.selectOne(new QueryWrapper<SmsAgreementApplicationDetail>()
                            .lambda()
                            .eq(SmsAgreementApplicationDetail::getApplicationId, allowVO.getApplyId())
                            .eq(SmsAgreementApplicationDetail::getDetailSort, paymentExamineDetail.getDetailSort() + 1));
            RangeTypeEnum rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_PERSON;
            if (nextDetail.getProcessObjectType() == AGREEMENT_OBJECT_TYPE_ROLE) {
                rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_ROLE;
            }
            List<String> rangeIDList = new ArrayList<>();
            rangeIDList.add(nextDetail.getProcessObjectId());
            newTipsUtil.allowContinueTips(allowVO.getApplyId(),
                    null,
                    rangeTypeEnum,
                    rangeIDList,
                    nextDetail.getId());
        }
        return CommonResult.success();
    }

    @Override
    @Transactional
    public ResponseResult forcedRejectAgreementApplication(SmsAgreementApplicationForcedVO forcedVO, String userId) {
        if(isNullOrEmpty(forcedVO.getApplyId(),forcedVO.getDetailAllowOption())){
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        //校验
        SmsAgreementApplication smsAgreementApplication = smsAgreementApplicationMapper.selectById(forcedVO.getApplyId());
        if(isNullOrEmpty(smsAgreementApplication)){
            return CommonResult.failed(CommonCodeEnum.AGREEMENT_NOT_EXIST);
        }
        //总状态只有待审批才能强制驳回
        Integer allowStatus = smsAgreementApplication.getAllowStatus();
        if(allowStatus != AGREEMENT_STATUS_WAIT_ALLOW){
            return CommonResult.failed(CommonCodeEnum.AGREEMENT_NOT_FORCED_REJECT);
        }
        //修改申请表状态为驳回
        smsAgreementApplication.setAllowStatus(AGREEMENT_STATUS_DENY);
        smsAgreementApplication.setEndTime(new Date());
        smsAgreementApplicationMapper.updateById(smsAgreementApplication);
        //修改节点状态 和审批人 时间
        SmsAgreementApplicationDetail agreementApplicationDetail = new SmsAgreementApplicationDetail();
        agreementApplicationDetail.setDetailAllowUserId(userId);
        agreementApplicationDetail.setDetailAllowStatus(AGREEMENT_STATUS_FORCED_REJECT);
        agreementApplicationDetail.setDetailAllowTime(new Date());
        agreementApplicationDetail.setDetailAllowOption(forcedVO.getDetailAllowOption());
        smsAgreementApplicationDetailMapper.update(agreementApplicationDetail, new LambdaQueryWrapper<SmsAgreementApplicationDetail>()
                .eq(SmsAgreementApplicationDetail::getApplicationId, forcedVO.getApplyId())
                .eq(SmsAgreementApplicationDetail::getDetailAllowStatus, AGREEMENT_STATUS_WAIT_ALLOW));
        //消息提醒
        newTipsUtil.cancelFinishTips(forcedVO.getApplyId());
        return CommonResult.success();
    }

    @Override
    @Transactional
    public ResponseResult deletedAgreementApplication(String applyId) {
        SmsAgreementApplication smsAgreementApplication = smsAgreementApplicationMapper.selectById(applyId);
        if (isNullOrEmpty(smsAgreementApplication)) {
            return CommonResult.failed(CommonCodeEnum.APPLICATION_NOT_EXIST);
        }

        //删除消息
        List<SmsNewTips> smsNewTipList = smsNewTipsMapper.selectList(new LambdaQueryWrapper<SmsNewTips>().eq(SmsNewTips::getEventId, applyId));
        if (!smsNewTipList.isEmpty()) {
            List<String> newTipsIdList = smsNewTipList.stream().map(SmsNewTips::getId).collect(Collectors.toList());
            smsNewTipsMapper.deleteBatchIds(newTipsIdList);
            smsNewTipsRecordMapper.delete(new LambdaQueryWrapper<SmsNewTipsRecord>().in(SmsNewTipsRecord::getRecordTipsId, newTipsIdList));
        }
        //删除申请表
        smsAgreementApplicationMapper.deleteById(applyId);

        //删除节点
        smsAgreementApplicationDetailMapper.delete(new LambdaQueryWrapper<SmsAgreementApplicationDetail>().eq(SmsAgreementApplicationDetail::getApplicationId, applyId));

        return CommonResult.success();
    }

    @Override
    public ResponseResult updateOpinion(SmsAgreementApplicationUpdateOpinionVo updateOpinionVo, String userId) {
        if (isNullOrEmpty(updateOpinionVo.getApplyId()) || isNullOrEmpty(updateOpinionVo.getDetailId())
                || isNullOrEmpty(updateOpinionVo.getDetailAllowStatus())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        //校验申请表
        SmsAgreementApplication smsAgreementApplication = smsAgreementApplicationMapper.selectById(updateOpinionVo.getApplyId());
        if (isNullOrEmpty(smsAgreementApplication)) {
            return CommonResult.failed(CommonCodeEnum.APPLICATION_NOT_EXIST);
        }
        //校验该节点是否存在,申请人是否是自己
        SmsAgreementApplicationDetail applicationDetail =
                smsAgreementApplicationDetailMapper.selectOne(new QueryWrapper<SmsAgreementApplicationDetail>()
                        .lambda()
                        .eq(SmsAgreementApplicationDetail::getApplicationId, updateOpinionVo.getApplyId())
                        .eq(SmsAgreementApplicationDetail::getId, updateOpinionVo.getDetailId())
                        .eq(SmsAgreementApplicationDetail::getDetailAllowUserId, userId));
        if (isNullOrEmpty(applicationDetail)) {
            return CommonResult.failed(CommonCodeEnum.AGREEMENT_PROCESS_NOT_EXIST);
        }
        if (updateOpinionVo.getDetailAllowStatus() != AGREEMENT_STATUS_PASS
                && updateOpinionVo.getDetailAllowStatus() != AGREEMENT_STATUS_DENY) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }


        //校验不是最后个节点时,下一个节点未审批才能修改意见
        Integer detailSort = applicationDetail.getDetailSort();
        Integer count = smsAgreementApplicationDetailMapper.selectCount(new LambdaQueryWrapper<>());
        if (!detailSort.equals(count)) {
            SmsAgreementApplicationDetail nextDetail = smsAgreementApplicationDetailMapper.selectOne(new QueryWrapper<SmsAgreementApplicationDetail>()
                    .lambda()
                    .eq(SmsAgreementApplicationDetail::getApplicationId, updateOpinionVo.getApplyId())
                    .eq(SmsAgreementApplicationDetail::getDetailSort, detailSort + 1));
            if (isNullOrEmpty(nextDetail)) {
                return CommonResult.failed(CommonCodeEnum.AGREEMENT_UPDATE_OPINION_FAIL);
            }
            Integer detailAllowStatus = nextDetail.getDetailAllowStatus();
            if (isNullOrEmpty(detailAllowStatus)) {
                return CommonResult.failed(CommonCodeEnum.AGREEMENT_UPDATE_OPINION_FAIL);
            }
        }
        applicationDetail.setDetailAllowStatus(updateOpinionVo.getDetailAllowStatus());
        if (!isNullOrEmpty(updateOpinionVo.getDetailAllowOpinion())) {
            applicationDetail.setDetailAllowOption(updateOpinionVo.getDetailAllowOpinion());
        }
        Date nowDate = new Date();
        applicationDetail.setDetailAllowTime(nowDate);

        if (applicationDetail.getProcessIsSign()) {
            if (isNullOrEmpty(updateOpinionVo.getDetailAllowSign())) {
                ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.INVALID_PARAM));
            }
            applicationDetail.setDetailAllowSign(updateOpinionVo.getDetailAllowSign());
        }
        if (applicationDetail.getProcessIsStamp()) {
            if (isNullOrEmpty(updateOpinionVo.getDetailAllowStamp())) {
                ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.INVALID_PARAM));
            }
            applicationDetail.setDetailAllowStamp(updateOpinionVo.getDetailAllowStamp());
        }
        smsAgreementApplicationDetailMapper.updateById(applicationDetail);
        //申请表修改状态
        String applicationId = smsAgreementApplication.getId();

        boolean is_done = false;
        //是最后个节点或者拒绝 修改申请表状态
        if (count.equals(detailSort) || updateOpinionVo.getDetailAllowStatus() == AGREEMENT_STATUS_DENY) {
            is_done = true;

            SmsAgreementApplication updateApplication = new SmsAgreementApplication();
            updateApplication.setId(updateOpinionVo.getApplyId());
            updateApplication.setEndTime(nowDate);
            updateApplication.setAllowStatus(updateOpinionVo.getDetailAllowStatus());
            smsAgreementApplicationMapper.updateById(updateApplication);
        }

        //节点驳回 重置其余节点状态
        SmsAgreementApplicationDetail updateDenyDetail =
                new SmsAgreementApplicationDetail();
        if (updateOpinionVo.getDetailAllowStatus() == AGREEMENT_STATUS_DENY) {

            updateDenyDetail.setDetailAllowStatus(AGREEMENT_STATUS_DENY_FINISH);
            smsAgreementApplicationDetailMapper.update(updateDenyDetail, new QueryWrapper<SmsAgreementApplicationDetail>()
                    .lambda()
                    .eq(SmsAgreementApplicationDetail::getApplicationId, updateOpinionVo.getApplyId())
                    .eq(SmsAgreementApplicationDetail::getDetailAllowStatus, AGREEMENT_STATUS_WAIT_ALLOW));
        } else{
            updateDenyDetail.setDetailAllowStatus(AGREEMENT_STATUS_WAIT_ALLOW);
            smsAgreementApplicationDetailMapper.update(updateDenyDetail, new QueryWrapper<SmsAgreementApplicationDetail>()
                    .lambda()
                    .eq(SmsAgreementApplicationDetail::getApplicationId, updateOpinionVo.getApplyId())
                    .eq(SmsAgreementApplicationDetail::getDetailAllowStatus, AGREEMENT_STATUS_DENY_FINISH));
        }

            //消息通知
            if (is_done) {
                boolean result_status = false;
                if (updateOpinionVo.getDetailAllowStatus() == AGREEMENT_STATUS_PASS) {
                    result_status = true;
                }
                newTipsUtil.allowFinishTips(updateOpinionVo.getApplyId(), userId, result_status);
            } else {
                //之前该节点驳回了,消息重新发起
                if (smsAgreementApplication.getAllowStatus() == AGREEMENT_STATUS_DENY && updateOpinionVo.getDetailAllowStatus() == AGREEMENT_STATUS_PASS) {
                    //查找消息标题
                    String tipsContent = null;
                    List<SmsNewTips> newTipsList = smsNewTipsMapper.selectList(new LambdaQueryWrapper<SmsNewTips>()
                            .eq(SmsNewTips::getEventId, updateOpinionVo.getApplyId())
                            .eq(SmsNewTips::getTipsType, TipsTypeEnum.TIPS_TYPE_ENUM_ALLOW.getValue())
                            .orderByDesc(SmsNewTips::getCreateTime));
                    if (!newTipsList.isEmpty()) {
                        tipsContent = newTipsList.get(0).getTipsContent();
                    }
                    smsAgreementApplication.setAllowStatus(AGREEMENT_STATUS_WAIT_ALLOW);
                    smsAgreementApplicationMapper.updateById(smsAgreementApplication);

                    RangeTypeEnum rangeTypeEnum;
                    if (applicationDetail.getProcessObjectType() == AGREEMENT_OBJECT_TYPE_PERSON) {
                        rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_PERSON;
                    } else {
                        rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_ROLE;
                    }
                    List<String> rangeList = new ArrayList<>();
                    rangeList.add(applicationDetail.getProcessObjectId());
                    newTipsUtil.addNewTips(TipsTypeEnum.TIPS_TYPE_ENUM_ALLOW,
                            userId,
                            rangeTypeEnum,
                            rangeList,
                            COPY_TYPE_ENUM_NONE,
                            null,
                            AppTypeEnum.APP_TYPE_ENUM_AGREEMENT_APPLICATION,
                            applicationId,
                            null,
                            null,
                            applicationDetail.getId(),
                            null,
                            null,
                            null,
                            tipsContent);

                }
            }
        return CommonResult.success();
    }

    @Override
    public ResponseResult updateAnnex(SmsAgreementApplicationUpdateAnnexVo updateAnnexVo, String userId) {
        if (isNullOrEmpty(updateAnnexVo.getApplyId())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        //校验申请表
        SmsAgreementApplication smsAgreementApplication = smsAgreementApplicationMapper.selectById(updateAnnexVo.getApplyId());
        if (isNullOrEmpty(smsAgreementApplication)) {
            return CommonResult.failed(CommonCodeEnum.APPLICATION_NOT_EXIST);
        }
        String applicationApplyUserId = smsAgreementApplication.getApplicationApplyUserId();
        if (!applicationApplyUserId.equals(userId)) {
            return CommonResult.failed(CommonCodeEnum.AGREEMENT_UPDATE_ANNEX_NOT_USER);
        }
        smsAgreementApplication.setAnnex(updateAnnexVo.getAnnex());
        smsAgreementApplicationMapper.updateById(smsAgreementApplication);
        return CommonResult.success();
    }

}




